www.gusucode.com > VC++写的C编译器源代码附设计文档-源码程序 > VC++写的C编译器源代码附设计文档-源码程序/code/C- Compiler/scaner.cpp

    // scaner.cpp : implementation file
// Download by http://www.NewXing.com

#include "stdafx.h"
#include "cminus.h"
#include "scaner.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CString ReservedKeywordList[] =
{
	"auto", "double", "int", "struct",
	"break", "else", "long", "switch",
	"case", "enum", "register", "typedef", 
	"char", "extern", "return", "union",
	"const", "float", "short", "unsigned",
	"continue", "for", "signed", "void",
	"default", "goto", "sizeof", "volatile",
	"do", "if", "static", "while",
	"read", "write", "printf",

	// operations
	"=", "+", "-", "*", "/", "%", "&", "|", "~", "!", "<", ">",
	
	// interpunctions
	"(", ")", "{", "}", "[", "]", ",", ".", ";", ":"
};

/*  *    CScaner
    *    Construction & destruction
  *	* *
   ***   Programer: 陆晓春
    *    Date:		2004.05.17             */

CScaner::CScaner( CString& str ) : CTokenizer( str )
{
	m_bPushedBack = FALSE;
	m_bTrace = FALSE;
	m_token.type = _ID;

	MapKeyword();
}

CScaner::~CScaner()
{
	if( m_fTraceFile.m_hFile != CFile::hFileNull )
		m_fTraceFile.Close();
}

/*  *    CScaner
    *    public functions
  *	* *
   ***   Programer: 陆晓春
    *    Date:		2004.05.17             */

// map keyword to TokenType
void CScaner::MapKeyword()
{
	m_KeyIndex.RemoveAll();
	m_KeyIndex.InitHashTable( MAX_KW );

	for( int i = 0; i < sizeof(ReservedKeywordList) / sizeof(*ReservedKeywordList); i++ )
		m_KeyIndex[ ReservedKeywordList[i] ] = (enum TokenType)i;
}

// trace function
void CScaner::Trace( LPCTSTR lpszPathname )
{
	ASSERT( m_fTraceFile.m_hFile == CFile::hFileNull );

	CFileException e;
	if( !m_fTraceFile.Open( lpszPathname, CFile::modeCreate | CFile::modeReadWrite, &e ) ) {
		OutputErrMsg( "failed to create scaner trace file: %s", lpszPathname );
		return;
	}

	m_bTrace = TRUE;
}

void CScaner::Flush()
{
	if( m_fTraceFile.m_hFile == CFile::hFileNull ) return;
	m_fTraceFile.Flush();
}

// get the next token
TOKEN& CScaner::NextToken()
{
	if( m_bPushedBack ) {
		m_bPushedBack = FALSE;
		return m_token;
	}
	if( m_token.type == _EOF ) return m_token;

	enum TokenType type;
	int val = CTokenizer::NextToken();
	int	lineno = LineNo();// the actual line the token is got from
	
	m_token.type = _ERROR;
	m_token.str = "error";

	if( val == TT_EOF ) {
		m_token.type = _EOF;
		m_token.str = "EOF";
		return m_token;
	}

	if( val == TT_WORD ) {
		if( m_KeyIndex.Lookup( m_sVal, type ) )
			m_token.type = type;
		else 
			m_token.type = _ID;
		m_token.str = m_sVal;
	} else if( val == TT_INTEGER || val == TT_REAL ) {
		m_token.type = _NUM;
		m_token.str = GetStrValue();
	} else if( val == TT_STRING ) {
		m_token.type = _STRING;
		m_token.str = m_sVal;
	} else if( val == TT_CHAR ) {
		m_token.type = _CHARACTER;
		m_token.str = (m_sVal.IsEmpty()) ? " " : CString( m_sVal[0] );
	} else if( val == TT_EOL ) {
		return NextToken();
	} else if( ::strchr( "=+-*/&|~!<>(){}[],.;:", val ) ) {
		m_token.str = (TCHAR)val;
		m_token.type = m_KeyIndex[ m_token.str ];

		// complex operations
		switch( val ) {
		case '=':
			if( CTokenizer::NextToken() == '=' ) {
				m_token.str = "==";
				m_token.type = EQ;
			} else
				CTokenizer::PushBack();
			break;
		case '!':
			if( CTokenizer::NextToken() == '=' ) {
				m_token.str = "!=";
				m_token.type = NEQ;
			} else
				CTokenizer::PushBack();
			break;
		case '+':
			if( CTokenizer::NextToken() == '=' ) {
				m_token.str = "+=";
				m_token.type = PLUS_ASSIGN;
			} else {
				CTokenizer::PushBack();
				if( CTokenizer::NextToken() == '+' ) {
					m_token.str = "++";
					m_token.type = PLUS_PLUS;
				} else
					CTokenizer::PushBack();
			}
			break;
		case '-':
			if( CTokenizer::NextToken() == '=' ) {
				m_token.str = "-=";
				m_token.type = MINUS_ASSIGN;
			} else {
				CTokenizer::PushBack();
				if( CTokenizer::NextToken() == '-' ) {
					m_token.str = "--";
					m_token.type = MINUS_MINUS;
				} else
					CTokenizer::PushBack();
			}
			break;
		case '*':
			if( CTokenizer::NextToken() == '=' ) {
				m_token.str = "*=";
				m_token.type = TIMES_ASSIGN;
			} else
				CTokenizer::PushBack();
			break;
		case '/':
			if( CTokenizer::NextToken() == '=' ) {
				m_token.str = "/=";
				m_token.type = DIV_ASSIGN;
			} else
				CTokenizer::PushBack();
			break;
		case '<':
			if( CTokenizer::NextToken() == '>' ) {
				m_token.str = "<>";
				m_token.type = NEQ;
			} else {
				CTokenizer::PushBack();
				if( CTokenizer::NextToken() == '=' ) {
					m_token.str = "<=";
					m_token.type = NGT;
				} else
					CTokenizer::PushBack();
			}
			break;
		case '>':
			if( CTokenizer::NextToken() == '=' ) {
				m_token.str = ">=";
				m_token.type = NLT;
			} else
				CTokenizer::PushBack();
			break;
		case '&':
			if( CTokenizer::NextToken() == '&' ) {
				m_token.str = "&&";
				m_token.type = LOGICAL_AND;
			} else
				CTokenizer::PushBack();
			break;
		case '|':
			if( CTokenizer::NextToken() == '|' ) {
				m_token.str = "||";
				m_token.type = LOGICAL_OR;
			} else
				CTokenizer::PushBack();
			break;
		}
	} else
		OutputErrMsg( "error in line %d: syntax error '%c'", LineNo(), (char)val );

	if( m_bTrace ) {
		CString temp;
		temp.Format( "line:%3d   Token Code: %.2d  %s\r\n", lineno, m_token.type, (LPCTSTR)m_token.str );
		try {
			m_fTraceFile.Write( (LPCTSTR)temp, temp.GetLength() );
		} catch( CFileException* ) {
			OutputErrMsg( "failed to write to file: %s", (LPCTSTR)m_fTraceFile.GetFilePath() );
		}
	}

	return m_token;
}

void CScaner::PushBack()
{
	m_bPushedBack = TRUE;
}